package model;

import exception.MyException;
import info.monitorenter.cpdetector.io.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * @author wxhntmy
 */
public class CpdetectorUtils {

    private final static Logger logger = LoggerFactory.getLogger(CpdetectorUtils.class);

    /**
     * 利用第三方开源包cpdetector获取文件编码格式.
     * --1、cpDetector内置了一些常用的探测实现类,这些探测实现类的实例可以通过add方法加进来,
     *   如:ParsingDetector、 JChardetFacade、ASCIIDetector、UnicodeDetector.
     * --2、detector按照“谁最先返回非空的探测结果,就以该结果为准”的原则.
     * --3、cpDetector是基于统计学原理的,不保证完全正确.
     * @param filePath 文件路径
     * @return 返回文件编码类型：GBK、UTF-8、UTF-16BE、ANSI、UTF-16LE
     */
    public static String getFileCharset(String filePath){
        CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();
        /*ParsingDetector可用于检查HTML、XML等文件或字符流的编码,
         * 构造方法中的参数用于指示是否显示探测过程的详细信息，为false不显示。
         */
        detector.add(new ParsingDetector(false));
        /*JChardetFacade封装了由Mozilla组织提供的JChardet，它可以完成大多数文件的编码测定。
         * 所以，一般有了这个探测器就可满足大多数项目的要求，如果你还不放心，可以再多加几个探测器，
         * 比如下面的ASCIIDetector、UnicodeDetector等。
         */
        detector.add(JChardetFacade.getInstance());
        // ASCIIDetector用于ASCII编码测定
        detector.add(ASCIIDetector.getInstance());
        // UnicodeDetector用于Unicode家族编码的测定
        detector.add(UnicodeDetector.getInstance());
        Charset charset = null;
        File file = new File(filePath);
        try {
            charset = detector.detectCodepage(file.toURI().toURL());
            //InputStream is = new BufferedInputStream(new FileInputStream(filePath));
            //charset = detector.detectCodepage(is, 8);
        } catch (IOException e) {
            try {
                throw new MyException("读取文件字符编码时文件URI异常！");
            } catch (MyException ex) {
                ex.printStackTrace();
            }
        }
        String charsetName = "GBK";
        if (null != charset){
            logger.info("File charsetName: {}",  charset.name());

            //windows记事本保存的 ANSI 编码格式会读成 US-ASCII
            if ("US-ASCII".equals(charset.name())) {
            /*
              GBK 英文字母和 iso8859-1 一致（兼容iso8859-1编码）。
              其中gbk编码能够用来同时表示繁体字和简体字，而gb2312只能表示简体字，gbk是兼容gb2312编码的
             */
                charsetName = "GBK";
            }
            //UTF-8、UTF-16BE 都可以读取出来
            else if (charset.name().startsWith("UTF")) {
                // 例如:UTF-8,UTF-16BE
                charsetName = charset.name();
            }
            //windows记事本保存的 UTF-16LE 编码格式会读成 windows-1252
            else if("windows-1252".equals(charset.name())){
                charsetName = String.valueOf(StandardCharsets.UTF_16LE);
            }
        }
        else {
            logger.info("CodepageDetectorProxy 获取到的字符编码为 null，字符编码 charsetName 使用默认值 GBK ！");
        }
        return charsetName;
    }
}
